//! Option 是Rust的系统类型，用来表示值不存在的可能，这在编程中是一个好的实践，它强制Rust检测和处理值不存在的情况

//unwrap,unwrap当遇到None值时会panic，如前面所说这不是一个好的工程实践。不过有些时候却非常有用,
// 在例子和简单快速的编码中 有的时候你只是需要一个小例子或者一个简单的小程序，输入输出已经确定，
// 你根本没必要花太多时间考虑错误处理，使用unwrap变得非常合适。

//查找指定字符的位置
fn find(haystack: &str, needle: char) -> Option<usize> {
    for (offset, c) in haystack.char_indices() {
        if c == needle {
            return Some(offset);
        }
    }
    None
}

//查找拓展名
fn extension_explicit(file_name: &str) -> Option<&str> {
    // match find(file_name, '.') {
    //     None => None,
    //     Some(i) => Some(&file_name[i+1..]),
    // }

    //使用map 去掉 match (map只是把值为Some(t)重新映射了一遍)
    //find(file_name, '.').map(|i|{&file_name[i+1..]})
    //使用and_then,and_then 会返回另一个Option
    find(file_name, '.').and_then(|i| {Some(&file_name[i+1..])})
}

#[test]
pub fn option_demo1(){
    match extension_explicit("foo.rs") {
        None => println!("no extension"),
        Some(ext) => assert_eq!(ext, "rs"),
    }
}
//map
#[test]
pub fn option_demo2(){
    let o: Option<&str> = Some("Ok");
    let o2: Option<String> = o.map(|s| {
        let mut string = String::from("hello");
        string.push_str(s);
        string
    });
    println!("{}", o2.unwrap());
}
// and_then
#[test]
pub fn option_demo3(){
    let o: Option<&str> = Some("Ok");
    let o2: Option<String>  = o.and_then(|s| {
        let mut string = String::from("hello ");
        string.push_str(s);
        return Some(string);
    });
    println!("{}", o2.unwrap());
}
//take 返回该Option,然后把该Option替换为None
#[test]
pub fn option_demo4(){
    let mut o: Option<&str> = Some("Ok");
    let t = o.take();
    println!("{}", t.unwrap());
    if o.is_none() {
        println!("o is none")
    }
}

// as mut

#[test]
pub fn option_demo5(){
    let mut o = Some(String::from("hello"));
    {
        //返回一个新的Option,持有实际对象的可变引用
        let new_o = o.as_mut();
        let r = new_o.unwrap();
        r.push_str(" world");
        //可变借用失效前，不可访问原变量
        //println!("{}", o.unwrap());
    }
    
    //可变借用失效，可以访问原变量
    println!("{}", o.unwrap());
}